package com.example;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.example.utils.BatUtils;
import org.jb2011.lnf.beautyeye.ch3_button.BEButtonUI;

import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumnModel;
import java.awt.*;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.io.File;
import java.util.Date;
import java.util.HashMap;
import java.util.Objects;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;


/**
 * @author user
 */
public class SwingArea extends JFrame {

    private static SwingArea instance = null;
    public static DefaultTableModel tableModel;
    public static JTextField fileText;
    public static JButton uploadAction;
    public static JLabel carryCountLabel;
    public static JLabel carryCountTodayLabel;
    public static boolean stopFlag = false;
    public static int MAIN_FRAME_HEIGHT;
    public static int MAIN_FRAME_WIDTH;
    public static int MAIN_FRAME_LOC_X;
    public static int MAIN_FRAME_LOC_Y;

    JLabel fileField;
    JLabel carryFrequencyField;
    JLabel upLoadField;
    Rectangle rectangle;

    private SwingArea() {
    }
    public static SwingArea getInstance() {
        if (null == instance) {
            synchronized (SwingArea.class) {
                if (null == instance) {
                    instance = new SwingArea();
                }
            }
        }
        return instance;
    }
    public void initUI() {
        this.setTitle("定时执行bat程序");
        this.setResizable(false);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        MAIN_FRAME_LOC_X = 100;
        MAIN_FRAME_LOC_Y = 100;
        MAIN_FRAME_WIDTH = 700;
        MAIN_FRAME_HEIGHT = 540;
        rectangle = new Rectangle(MAIN_FRAME_LOC_X, MAIN_FRAME_LOC_Y, MAIN_FRAME_WIDTH, MAIN_FRAME_HEIGHT);
        this.setBounds(rectangle);
        this.setLayout(new BorderLayout());

        // 监听父窗口位置
        addComponentListener(new ComponentAdapter() {
            @Override
            public void componentMoved(ComponentEvent e) {
                Component comp = e.getComponent();
                //更新当前窗口所在的坐标
                MAIN_FRAME_LOC_X = comp.getX();
                MAIN_FRAME_LOC_Y = comp.getY();
            }
        });

        initTopPanel();
        initLogPanel();
        initUnderPanel();

        this.setVisible(true);
    }

    public void initTopPanel(){
        JPanel topPanel = new JPanel();
        topPanel.setBackground(Color.lightGray);
        topPanel.setLayout(new FlowLayout());

        this.add(topPanel,BorderLayout.NORTH);


        JLabel label = new JLabel("文件");
        topPanel.add(label);
        //创建JTextField，16表示16列，用于JTextField的宽度显示而不是限制字符个数
        fileText = new JTextField(14);
        topPanel.add(fileText);


        AtomicReference<JFileChooser> file = new AtomicReference<>(new JFileChooser());

        JButton openBtn = new JButton("选择");
        openBtn.addActionListener(e -> file.set(showFileOpenDialog(this, fileText)));
        openBtn.setUI(new BEButtonUI().setNormalColor(BEButtonUI.NormalColor.blue));
        openBtn.setFont(new Font("宋体", Font.BOLD,12));
        openBtn.setForeground(Color.white);//字体颜色
        topPanel.add(openBtn);

        JLabel carryLabel = new JLabel("执行频率");
        JComboBox<String> comboBox = new JComboBox<String>();//创建一个下拉列表框c1
        comboBox.addItem("仅执行一次");
        comboBox.addItem("30s执行一次");
        comboBox.addItem("1min执行一次");
        comboBox.addItem("3min执行一次");
        comboBox.addItem("5min执行一次");
        comboBox.addItem("30min执行一次");
        comboBox.addItem("1h执行一次");
        comboBox.addItem("6h执行一次");
        comboBox.addItem("12h执行一次");
        comboBox.addItem("24h执行一次");
        topPanel.add(carryLabel);
        topPanel.add(comboBox);


        JButton action = new JButton("执行");

        action.addActionListener(e -> action(file.get(), comboBox));
        action.setUI(new BEButtonUI().setNormalColor(BEButtonUI.NormalColor.green));
        action.setFont(new Font("宋体", Font.BOLD,12));
        action.setForeground(Color.white);
        topPanel.add(action);

        JButton stopAction = new JButton("停止");

        stopAction.addActionListener(e -> stop());
        stopAction.setUI(new BEButtonUI().setNormalColor(BEButtonUI.NormalColor.green));
        stopAction.setFont(new Font("宋体", Font.BOLD,12));
        stopAction.setForeground(Color.white);
        topPanel.add(stopAction);

        JButton cleanAction = new JButton("清空");

        cleanAction.addActionListener(e -> clean());
        cleanAction.setUI(new BEButtonUI().setNormalColor(BEButtonUI.NormalColor.green));
        cleanAction.setFont(new Font("宋体", Font.BOLD,12));
        cleanAction.setForeground(Color.white);
        topPanel.add(cleanAction);

        uploadAction = new JButton("上传");
        uploadAction.addActionListener(e -> upload());
        uploadAction.setUI(new BEButtonUI().setNormalColor(BEButtonUI.NormalColor.blue));
        uploadAction.setFont(new Font("宋体", Font.BOLD,12));
        uploadAction.setForeground(Color.white);
        topPanel.add(uploadAction);

    }

    public void initLogPanel(){
        // 打印日志窗体
        Panel logPanel = new Panel();
        logPanel.setBackground(Color.CYAN);
        logPanel.setLayout(new BorderLayout());

        this.add(logPanel, BorderLayout.CENTER);

        JTable table = new JTable();
        tableModel=(DefaultTableModel) table.getModel();
        tableModel.setColumnIdentifiers(new Object[]{"时间","日志"});//获得表格模型
        table.setModel(tableModel);

        // 调整列宽
        TableColumnModel colModel = table.getColumnModel();
        colModel.getColumn(0).setPreferredWidth(100);
        colModel.getColumn(1).setPreferredWidth(600);

        JScrollPane scrollPane = new JScrollPane(table);
        this.add(scrollPane, BorderLayout.CENTER);
    }

    public void initUnderPanel(){
        // 底部信息窗体
        Panel underPanel = new Panel();
        this.add(underPanel, BorderLayout.SOUTH);
        underPanel.setLayout(new GridLayout(2,1, 0,-8));

        Panel underPanel1 = new Panel();
        underPanel.add(underPanel1);
        underPanel1.setBackground(Color.white);
        underPanel1.setLayout(new FlowLayout(FlowLayout.LEFT));


        JLabel fileFildTitle = new JLabel("执行文件：");
        fileFildTitle.setBounds(130, 150, 150, 30);
        underPanel1.add(fileFildTitle);
        fileField = new JLabel("无");
        underPanel1.add(fileField);

        JLabel carryFrequencyTitle = new JLabel("执行频率：");
        underPanel1.add(carryFrequencyTitle);
        carryFrequencyField = new JLabel("无");
        underPanel1.add(carryFrequencyField);

        JLabel uploadTitle = new JLabel("是否主动上传：");
        underPanel1.add(uploadTitle);
        upLoadField = new JLabel("否");
        underPanel1.add(upLoadField);

        Panel underPanel2 = new Panel();
        underPanel.add(underPanel2);
        underPanel2.setBackground(Color.white);
        underPanel2.setLayout(new FlowLayout(FlowLayout.LEFT));


        JLabel carryCount = new JLabel("执行次数：");
        underPanel2.add(carryCount);
        carryCountLabel = new JLabel("0");
        underPanel2.add(carryCountLabel);

        JLabel carryCountToday = new JLabel("今日执行次数：");
        underPanel2.add(carryCountToday);
        carryCountTodayLabel = new JLabel("0");
        underPanel2.add(carryCountTodayLabel);
    }

    private void action(JFileChooser fileChooser, JComboBox<String> comboBox) {
        if (null == fileChooser || null == fileChooser.getSelectedFile()) {
            JOptionPane.showMessageDialog(this, "请先选择要处理的文件！╮(╯▽╰)╭", "警告！",JOptionPane.WARNING_MESSAGE);
            return;
        }
        fileField.setText(fileText.getText());
        if (MyDialog.flagBox.isSelected()){
            upLoadField.setText("是");
        }
        // 开启定时任务
        String selectItem = Objects.requireNonNull(comboBox.getSelectedItem()).toString();
        carryFrequencyField.setText(selectItem);
        if ("仅执行一次".equals(selectItem)){
            runBat(fileText.getText());
        }else {
            HashMap<String, Object> itemMap = selectItemToInt(selectItem);
            ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
            executor.scheduleAtFixedRate(
                    () -> runBat(fileText.getText()),
                    0,
                    (Long) itemMap.get("period"),
                    (TimeUnit) itemMap.get("unit"));
        }
    }

    private void stop() {
        stopFlag = true;
        upLoadField.setText("否");
    }

    private void clean() {
        tableModel.setRowCount(0);
    }

    private void upload() {
//        repaint(MAIN_FRAME_LOC_X, MAIN_FRAME_LOC_Y, MAIN_FRAME_WIDTH, MAIN_FRAME_HEIGHT);
        uploadAction.setEnabled(false);
        if(StrUtil.isEmpty(fileText.getText())){
            JOptionPane.showMessageDialog(this, "请选择文件", "提示", JOptionPane.WARNING_MESSAGE);
        }else {
            MyDialog.getInstance(this).initUI();
        }
    }

    /*
     * 打开文件
     */
    private JFileChooser showFileOpenDialog(Component parent, JTextField fileText) {

        JFileChooser jFileChooser = new JFileChooser();
        jFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
        jFileChooser.setMultiSelectionEnabled(false);
        // 设置默认使用的文件过滤器
//        jFileChooser.setFileFilter(new FileNameExtensionFilter("excel(*.xlsx, *.xls)", "xls", "xlsx"));
        jFileChooser.setFileFilter(new FileNameExtensionFilter("bat", "bat"));
        // 打开文件选择框（线程将被阻塞, 直到选择框被关闭）
        int result = jFileChooser.showOpenDialog(parent);

        if (result == JFileChooser.APPROVE_OPTION) {
            // 如果点击了"确定", 则获取选择的文件路径
            File file = jFileChooser.getSelectedFile();

            // 如果允许选择多个文件, 则通过下面方法获取选择的所有文件
            // File[] files = fileChooser.getSelectedFiles();
            fileText.setText("");
            fileText.setText(file.getAbsolutePath() + "\n\n");
        }
        return jFileChooser;
    }


    public boolean runBat(String batPath){
        boolean flag = false;
        File batFile = new File(batPath);
        boolean batFileExist = batFile.exists();
        if (batFileExist) {
            int count = Integer.parseInt(SwingArea.carryCountLabel.getText());
            int todayCount = Integer.parseInt(SwingArea.carryCountTodayLabel.getText());
            SwingArea.carryCountLabel.setText(String.valueOf(count + 1));
            SwingArea.carryCountTodayLabel.setText(String.valueOf(todayCount + 1));

            if (BatUtils.execCommand(batPath)){
                MyDialog.getInstance(this).uploadToGit(2);
            }
        } else {
            String time = DateUtil.format(new Date(), "MM-dd HH:mm:ss");
            SwingArea.tableModel.addRow(new Object[]{time, "找不到脚本文件"});
        }
        return flag;
    }

    private HashMap<String, Object> selectItemToInt(String selectItem){
        HashMap<String, Object> map = new HashMap<>();

        switch (selectItem){
            case "仅执行一次" :
                map.put("period", 1000000L);
                map.put("unit", TimeUnit.DAYS);
                break;
            case "30s执行一次" :
                map.put("period", 30L);
                map.put("unit", TimeUnit.SECONDS);
                break;
            case "1min执行一次" :
                map.put("period", 1L);
                map.put("unit", TimeUnit.MINUTES);
                break;
            case "3min执行一次" :
                map.put("period", 3L);
                map.put("unit", TimeUnit.MINUTES);
                break;
            case "5min执行一次" :
                map.put("period", 5L);
                map.put("unit", TimeUnit.MINUTES);
                break;
            case "30min执行一次" :
                map.put("period", 30L);
                map.put("unit", TimeUnit.MINUTES);
                break;
            case "1h执行一次" :
                map.put("period", 1L);
                map.put("unit", TimeUnit.HOURS);
                break;
            case "6h执行一次" :
                map.put("period", 6L);
                map.put("unit", TimeUnit.HOURS);
                break;
            case "12h执行一次" :
                map.put("period", 12L);
                map.put("unit", TimeUnit.HOURS);
                break;
            case "24h执行一次" :
                map.put("period", 24L);
                map.put("unit", TimeUnit.HOURS);
                break;
        }
        return map;
    }
}
